#include <check.h>
#include "test_ksamp_options.h"

#include <signal.h>
#include <assert.h>
#include "ksamp_options.h"

static Options *options = NULL; /* Compartida por los tests... */

static void setup (void) {
	options = NULL;
}

static void teardown (void) {
	if (options != NULL)
		options_destroy (options);
}

/* Testeo de precondiciones */
START_TEST (test_parse_negative)
{
	char *argv[] = {"ksamp", NULL};
	options = parse_options (-1, argv);
}
END_TEST

START_TEST (test_parse_null)
{
	options = parse_options (1, NULL);
}
END_TEST

START_TEST (test_mode_invalid)
{
	char *argv[] = {"ksamp", "x", NULL};
	ksamp_mode m;
	options = parse_options (2, argv);
	assert (!options_is_valid (options));
	m = options_get_mode(options); /* Debería fallar */
}
END_TEST

START_TEST (test_duration_invalid)
{
	char *argv[] = {"ksamp", "x", NULL};
	int d;
	options = parse_options (2, argv);
	assert (!options_is_valid (options));
	d = options_get_duration(options); /* Debería fallar */
}
END_TEST

START_TEST (test_interval_invalid)
{
	char *argv[] = {"ksamp", "x", NULL};
	int i;
	options = parse_options (2, argv);
	assert (!options_is_valid (options));
	i = options_get_interval(options); /* Debería fallar */
}
END_TEST

START_TEST (test_error_valid)
{
	char *argv[] = {"ksamp", NULL};
	const_bstring e;
	options = parse_options (1, argv);
	assert (options_is_valid (options));
	e = options_get_error(options); /* Debería fallar, no hay error */
}
END_TEST

START_TEST (test_interval_badmode)
{
	char *argv[] = {"ksamp", NULL};
	int i;
	options = parse_options (1, argv);
	assert (options_get_mode (options) != MODE_LOOPED);
	i = options_get_interval (options); /* Debería fallar, modo != looped */
}
END_TEST

START_TEST (test_duration_badmode)
{
	char *argv[] = {"ksamp", "-s", NULL};
	int d;
	options = parse_options (2, argv);
	assert (options_get_mode (options) != MODE_LOOPED);
	d = options_get_duration (options); /* Debería fallar, modo != looped */
}
END_TEST

/* Testeo de funcionalidad */

START_TEST (test_no_arguments)
{
	char *argv[] = {"ksamp", NULL};
	options = parse_options (1, argv);
	fail_unless (options_is_valid (options));
	fail_unless (options_get_mode (options) == MODE_SIMPLE);
}
END_TEST

START_TEST (test_stat_mode)
{
	char *argv[] = {"ksamp", "-s", NULL};
	options = parse_options (2, argv);
	fail_unless (options_is_valid (options));
	fail_unless (options_get_mode (options) == MODE_STATISTICS);
}
END_TEST

START_TEST (test_loop_mode)
{
	char *argv[] = {"ksamp", "-l", "2", "10", NULL};
	options = parse_options (4, argv);
	fail_unless (options_is_valid (options));
	fail_unless (options_get_mode (options) == MODE_LOOPED);
	fail_unless (options_get_interval (options) == 2);
	fail_unless (options_get_duration (options) == 10);
}
END_TEST

START_TEST (test_zero_duration)
{
	char *argv[] = {"ksamp", "-l", "2", "0", NULL};
	options = parse_options (4, argv);
	/* Todo bien si pedimos duración 0 */
	fail_unless (options_get_duration (options) == 0);
}
END_TEST

START_TEST (test_empty_error_for_help)
{
	char *argv[] = {"ksamp", "--help", NULL};
	options = parse_options (2, argv);
	fail_unless (!options_is_valid (options));
	fail_unless (blength (options_get_error (options)) == 0);
}
END_TEST

/* Validación */

START_TEST (test_invalid_other)
{
	char *argv[] = {"ksamp", "-x", NULL}; /* Pasamos una opción que no existe */
	options = parse_options (2, argv);
	fail_unless (!options_is_valid (options));
}
END_TEST

START_TEST (test_invalid_mixed)
{
	char *argv[] = {"ksamp", "-s", "-l", "1", "10", NULL};
	options = parse_options (5, argv);
	fail_unless (!options_is_valid (options));
}
END_TEST

START_TEST (test_invalid_nonnumeric_interval)
{
	char *argv[] = {"ksamp", "-l", "xxx", "10", NULL};
	options = parse_options (4, argv);
	fail_unless (!options_is_valid (options));
}
END_TEST

START_TEST (test_invalid_nonnumeric_duration)
{
	char *argv[] = {"ksamp", "-l", "1", "xxx", NULL};
	options = parse_options (4, argv);
	fail_unless (!options_is_valid (options));
}
END_TEST

START_TEST (test_invalid_negative_interval)
{
	char *argv[] = {"ksamp", "-l", "-9", "10", NULL};
	options = parse_options (4, argv);
	fail_unless (!options_is_valid (options));
}
END_TEST

START_TEST (test_invalid_negative_duration)
{
	char *argv[] = {"ksamp", "-l", "9", "-10", NULL};
	options = parse_options (4, argv);
	fail_unless (!options_is_valid (options));
}
END_TEST

START_TEST (test_invalid_zero_interval)
{
	char *argv[] = {"ksamp", "-l", "0", "10", NULL};
	options = parse_options (4, argv);
	/* El intervalo no puede ser 0 */
	fail_unless (!options_is_valid (options));
}
END_TEST

/* Armado de la test suite */

Suite *ksamp_options_suite (void)
{
	Suite *s = suite_create ("ksamp_options");
	TCase *tc_preconditions = tcase_create ("Precondition");
	TCase *tc_functionality = tcase_create ("Functionality");
	TCase *tc_validation = tcase_create ("Validation");

	/* Precondiciones */
	tcase_add_checked_fixture (tc_preconditions, setup, teardown);
	tcase_add_test_raise_signal (tc_preconditions, test_parse_negative, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_parse_null, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_mode_invalid, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_interval_invalid, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_duration_invalid, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_error_valid, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_interval_badmode, SIGABRT);
	tcase_add_test_raise_signal (tc_preconditions, test_duration_badmode, SIGABRT);
	suite_add_tcase (s, tc_preconditions);

	/* Funcionalidad */
	tcase_add_checked_fixture (tc_functionality, setup, teardown);
	tcase_add_test (tc_functionality, test_no_arguments);
	tcase_add_test (tc_functionality, test_stat_mode);
	tcase_add_test (tc_functionality, test_loop_mode);
	tcase_add_test (tc_functionality, test_zero_duration);
	tcase_add_test (tc_functionality, test_empty_error_for_help);
	suite_add_tcase (s, tc_functionality);
	
	/* Validación (detecta parámetros incorrectos) */
	tcase_add_checked_fixture (tc_validation, setup, teardown);
	tcase_add_test (tc_validation, test_invalid_other);
	tcase_add_test (tc_validation, test_invalid_mixed);
	tcase_add_test (tc_validation, test_invalid_nonnumeric_interval);
	tcase_add_test (tc_validation, test_invalid_nonnumeric_duration);
	tcase_add_test (tc_validation, test_invalid_negative_interval);
	tcase_add_test (tc_validation, test_invalid_negative_duration);
	tcase_add_test (tc_validation, test_invalid_zero_interval);
	suite_add_tcase (s, tc_validation);

	return s;
}

